<?php
//---------------------------------------------------------
//               Buddha Bless, No Bug !
//         User: wuxuehai Date: 2018/11/29 Time: 11:16 AM
//---------------------------------------------------------

namespace common\components\upload;

use OSS\OssClient;
use Yii;
use common\models\File;
use yii\helpers\Url;
use yii\web\UploadedFile;
use yii\base\InvalidConfigException;
use common\components\BaseComponents;
use common\components\AliyunOss;

/**
 *
 * @property string $md5
 * @property string $random
 * @property string $extension
 * @property string $saveName
 * @property string $relativePath
 * @property string $absolutelyPath
 * @property string $size
 * @property-read void $savePath
 * @property string $baseName
 * Class Upload
 * @package common\components\upload
 */
class Upload extends BaseComponents
{

    /* @var $fileInstance UploadedFile */
    public $fileInstance;

    public $filedName = 'file';

    public $basePath = '/uploads/file/';

    public $maxSize = 200000000;

    public $allowExtension = ['jpg', 'jpeg', 'png', 'gif', 'docx', 'doc', 'pdf', 'svg', 'mp4'];

    public $error = '';

    public $exist = null;


    public function init()
    {
        $this->setRandom(uniqid());
    }

    /**
     * @return bool
     */
    public function upload()
    {
        try {

            //创建保存目录
            $this->makeUploadDir();

            //获取上传文件
            $this->getFileInstance();

            //验证文件
            $this->validate();

            //保存到本地目录
            $this->moveFileToLocal();

            //上传到Oss
            $this->uploadToOss();

            //保存文件信息
            $this->saveFileInfo();

            return true;
        } catch (\Exception $e) {
            $this->error = $e->getMessage();
            return false;
        }
    }

    public function setMd5($hash)
    {
        $this->md5 = $hash;
    }

    public function setRandom($str)
    {
        $this->random = $str;
    }

    public function makeUploadDir()
    {
        if (!file_exists(Yii::$app->params['uploadPath'] . $this->savePath)) {
            if (!mkdir(Yii::$app->params['uploadPath'] . $this->savePath, '0755', true)) {
                throw new InvalidConfigException('上传目录创建失败');
            }
        }
    }

    public function getRandom()
    {
        return uniqid();
    }

    public function getSaveName()
    {
        return md5($this->fileInstance->baseName . $this->random);
    }

    public function getSavePath()
    {
        return $this->basePath . date('Ymd') . DIRECTORY_SEPARATOR;
    }

    public function getRelativePath()
    {
        return $this->savePath . $this->saveName . '.' . $this->fileInstance->extension;
    }

    public function setRelativePath($path)
    {
        return $this->relativePath = $path;
    }

    public function getAbsolutelyPath()
    {
        return Yii::$app->params['uploadPath'] . $this->relativePath;
    }

    protected function getFileInstance()
    {
        $this->fileInstance = UploadedFile::getInstanceByName($this->filedName);
    }

    /**
     * @throws InvalidConfigException
     */
    protected function validate()
    {
        if (empty($this->fileInstance)) {
            throw new InvalidConfigException(Yii::t('app', 'upload file fail'));
        }

        if ($this->fileInstance->size > $this->maxSize) {
            throw new InvalidConfigException(Yii::t('app', 'file size max {maxSize}', ['maxsize' => $this->maxSize]));
        }

        if (!in_array($this->fileInstance->extension, $this->allowExtension)) {
            throw new InvalidConfigException(Yii::t('app', 'file suffix that is not allowed'));
        }
    }

    /**
     *
     */
    protected function saveFileInfo()
    {
        //文件记录入库
        if (!$this->exist) {
            $fileModel = new File();

            $fileModel->md5 = $this->md5;
            $fileModel->path = $this->relativePath;
            $fileModel->identity_id = Yii::$app->user->id;
            $fileModel->identity_name = Yii::$app->user->identity->username;

            $fileModel->size = $this->fileInstance->size;
            $fileModel->name = $this->fileInstance->baseName;
            $fileModel->extension = $this->fileInstance->extension;

            $fileModel->save(false);
        }

    }

    /**
     * @throws \OSS\Core\OssException
     * @throws \yii\base\InvalidConfigException
     */
    protected function uploadToOss()
    {
        if (Yii::$app->params['useOss'] && !$this->exist) {
            /** @var AliyunOss $oss */
            $oss = \Yii::$app->get('oss');

            $name = trim($this->relativePath, '/');

            if (in_array(strtolower($this->fileInstance->extension), ['mp4'])) {
                $res = $oss->upload($name, $this->absolutelyPath, [
                    OssClient::OSS_HEADERS => [
                        'x-oss-object-acl' => 'private',
                    ],
                ]);
            } else {
                $res = $oss->upload($name, $this->absolutelyPath);
            }


            $this->setRelativePath(Url::ensureScheme($res['info']['url'], ''));
        }
    }

    /**
     * @throws InvalidConfigException
     */
    protected function moveFileToLocal()
    {
        $this->setMd5(md5_file($this->fileInstance->tempName));
        $exist = File::find()->where(['md5' => $this->md5])->orderBy('id DESC')->one();

        if ($exist) {
            $this->relativePath = $exist->path;
            $this->exist = $exist;
        } else {
            if (!$exist && !$this->fileInstance->saveAs($this->absolutelyPath)) {
                throw new InvalidConfigException(Yii::t('app', 'save file fail'));
            }
        }
    }
}
